package sk.ygor.raynor.rebind.common


import com.google.gwt.core.ext.typeinfo.{JType, JClassType}
import com.google.gwt.core.ext.{UnableToCompleteException, GeneratorContext, TreeLogger}
import com.google.gwt.user.rebind.{SourceWriter, ClassSourceFileComposerFactory}
import java.lang.String


abstract class ScalaGeneratorWorker(logger: TreeLogger, context: GeneratorContext, inputClassName: String) 
        extends AnyRef with GeneratorUtils {
  val inputClassType: JClassType = context.getTypeOracle.getType(inputClassName)

  val inputClassPackageName = inputClassType.getPackage.getName
  val inputClassSimpleName = inputClassType.getSimpleSourceName

  val generatedClassPackage = inputClassPackageName
  val generatedClassName = inputClassSimpleName + "Impl"

  def generate: String = {
    try {
      val printWriter = context.tryCreate(logger, generatedClassPackage, generatedClassName);
      // print writer if null, source code has ALREADY been generated, return
      if (printWriter != null) {
        val composer = new ClassSourceFileComposerFactory(generatedClassPackage, generatedClassName)
        generateHeader(composer)
        val sourceWriter = composer.createSourceWriter(context, printWriter)
        generateBody(sourceWriter)
        sourceWriter.outdent()
        sourceWriter.println("}")
        context.commit(logger, printWriter)
      }
      generatedClassPackage + "." + generatedClassName;
    } catch {
      case e => {
        logger.log(TreeLogger.Type.ERROR, e.getMessage, e)
        throw new UnableToCompleteException()
      }
    }
  }

  def generateHeader(composer: ClassSourceFileComposerFactory)

  def generateBody(sourceWriter: SourceWriter)

  implicit def richComposer(composer: ClassSourceFileComposerFactory) = new RichComposer(composer)

  implicit def clazzSourceFileName(clazz: Class[_]) = clazz.getName.replaceAll("\\$", "\\.") 

  class RichComposer(composer: ClassSourceFileComposerFactory) {
    def addImports(classes: Class[_]*) = for (clazz <- classes) {
      composer addImport clazz
    }
  }

}

class GeneratorResult(val serializerType: String, val remainingTypes: Set[JType])

case class InputContext(logger: TreeLogger, context: GeneratorContext, inputType: JType) {
  def withOtherType(otherType: JType) = InputContext(logger, context, otherType) 
}
